from server.models import User, Article, Comment, Notification, UserInfo
from rest_framework import serializers
from django_redis import get_redis_connection


class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = User
        fields = ['id',  'username', 'password', 'email', 'info', 'email_validated']
        extra_kwargs = {
            'username': {'read_only': True},
            'password': {'write_only': True},
            'email': {'read_only': True}
        }


class UserInfoSerializer(serializers.ModelSerializer):

    class Meta:
        model = UserInfo
        fields = ['id', 'nickname', 'avatar', 'gender',
                  'my_like', 'followers', 'followees', 'user']


def _get_thumbups(model_name_lower, obj):
    cache_key = f'{model_name_lower}_thumbups:{obj.id}'
    con = get_redis_connection('default')
    if con.exists(cache_key):
        return ';'.join([u.decode() for u in con.smembers(cache_key)])
    if obj.thumbuped_by is not None:
        cache_values = obj.thumbuped_by.split(';')
        con.sadd(cache_key, *cache_values)
    return obj.thumbuped_by


class ArticleSerializer(serializers.ModelSerializer):

    author_detail = serializers.SerializerMethodField()
    thumbuped_by = serializers.SerializerMethodField()
    comment_count = serializers.SerializerMethodField()

    class Meta:
        model = Article
        fields = ['id', 'author', 'author_detail', 'content',
                  'created_at', 'last_modified_at', 'liked_by', 'thumbuped_by', 'comment_count']
        # extra_kwargs = {
        #     'thumbuped_by': {'write_only': True}
        # }

    def get_author_detail(self, obj):
        author = obj.author
        request = self.context.get('request')
        return {
            'nickname': author.nickname,
            'id': author.user.id,
            'avatar': request.build_absolute_uri(author.avatar.url) if author.avatar else ""
        }

    def get_thumbuped_by(self, obj):
        return _get_thumbups('article', obj)

    def get_comment_count(self, obj):
        return obj.comments.count()


class CommentSerializer(serializers.ModelSerializer):

    thumbuped_by = serializers.SerializerMethodField()
    author_detail = serializers.SerializerMethodField()
    parent_author_detail = serializers.SerializerMethodField()
    have_descendants = serializers.SerializerMethodField()

    class Meta:
        model = Comment
        fields = ['id', 'author', 'author_detail', 'content', 'created_at',
                  'parent', 'parent_author_detail', 'is_deleted', 'thumbuped_by', 'article', 'have_descendants']
        # extra_kwargs = {
        #     'thumbuped_by': {'write_only': True}
        # }

    def get_thumbuped_by(self, obj):
        return _get_thumbups('comment', obj)

    def get_author_detail(self, obj):
        author = obj.author
        request = self.context.get('request')
        return {
            'nickname': author.nickname,
            'id':author.user.id,
            'avatar': request.build_absolute_uri(author.avatar.url) if author.avatar else ""
        }

    def get_parent_author_detail(self, obj):
        parent = obj.parent
        # request = self.context.get('request')
        return {
            'nickname': parent.author.nickname if parent else None,
            'id':parent.author.user.id  if parent else None,
            # 'avatar': request.build_absolute_uri(author.avatar.url)
        }

    def get_have_descendants(self, obj):
        return not obj.is_leaf_node()


class NotificationSerializer(serializers.ModelSerializer):

    obj_detail = serializers.SerializerMethodField()
    comment_content = serializers.SerializerMethodField()
    new_comment_content = serializers.SerializerMethodField()

    class Meta:
        model = Notification
        exclude = []

    def get_obj_detail(self, obj):
        request = self.context.get('request')
        return {
            'nickname': obj.obj.nickname,
            'id': obj.obj.user.id,
            'avatar': request.build_absolute_uri(obj.obj.avatar.url) if obj.obj.avatar else ""
        }

    def get_comment_content(self, obj):
        return {
            'content': obj.comment.content if obj.comment else None
        }

    def get_new_comment_content(self, obj):
        return {
            'content': obj.new_comment.content if obj.new_comment else None
        }